﻿using IntoCommon.Util;
using S7.Net.Types;
using System;
using System.Collections.ObjectModel;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Prism.Mvvm;
using IntoStationRepair.Models;
using IntoStationRepair.PLC;
using IntoStationSystem.Models;

namespace IntoStationRepair.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        public TightenGunModel Tighten { get; set; } = new TightenGunModel();

        public Service Service = new Service();
        public ObservableCollection<Msg> Messages { get; set; } = new ObservableCollection<Msg>();
        public ObservableCollection<Msg> StepTips { get; set; } = new ObservableCollection<Msg>();

        private SerialPort serialPort = new SerialPort();

        private TrigR sendMsgTrigger = new TrigR();
        private TrigR resetShiftBtnTrigger = new TrigR();

        public string TrayID = string.Empty;


        private ProductIdentity identity = new ProductIdentity();


        private bool isRepairOP10 = false;
        private bool isRepairOP20 = false;
        private bool isRepairOP30 = false;
        private bool isRepairOP40 = false;
        private bool isPrepareRepair = true;
        private bool isEnableOP10 = true;
        private bool isEnableOP20 = true;
        private bool isEnableOP30 = true;
        private bool isEnableOP40 = true;

        private string op10Code;
        private string op10Code1;
        private string op10Code2;
        private string op20Code;
        private string op30Code;
        private string op40Code;
        private string op10Result;
        private string op20Result;
        private string op30Result;
        private string op40Result;
        private string confirmResult;
        private string resetResult;
        private int stepIndex;

        public bool IsEnableOP10
        {
            get => isEnableOP10; set => SetProperty(ref isEnableOP10, value);
        }
        public bool IsEnableOP20
        {
            get => isEnableOP20; set => SetProperty(ref isEnableOP20, value);
        }
        public bool IsEnableOP30
        {
            get => isEnableOP30; set => SetProperty(ref isEnableOP30, value);
        }
        public bool IsEnableOP40
        {
            get => isEnableOP40; set => SetProperty(ref isEnableOP40, value);
        }
        public string OP10Code
        {
            get => op10Code; set => SetProperty(ref op10Code, value);
        }
        public string OP10Code1
        {
            get => op10Code1; set => SetProperty(ref op10Code1, value);
        }
        public string OP10Code2
        {
            get => op10Code2; set => SetProperty(ref op10Code2, value);
        }

        public string OP20Code
        {
            get => op20Code; set => SetProperty(ref op20Code, value);
        }
        public string OP30Code
        {
            get => op30Code; set => SetProperty(ref op30Code, value);
        }
        public string OP40Code
        {
            get => op40Code; set => SetProperty(ref op40Code, value);
        }
        public string OP10Result
        {
            get => op10Result; set => SetProperty(ref op10Result, value);
        }
        public string OP20Result
        {
            get => op20Result; set => SetProperty(ref op20Result, value);
        }
        public string OP30Result
        {
            get => op30Result; set => SetProperty(ref op30Result, value);
        }
        public string OP40Result
        {
            get => op40Result; set => SetProperty(ref op40Result, value);
        }
        public string ConfirmResult
        {
            get => confirmResult; set => SetProperty(ref confirmResult, value);
        }
        public string ResetResult
        {
            get => resetResult; set => SetProperty(ref resetResult, value);
        }
        public bool IsRepairOP10
        {
            get => isRepairOP10; set => SetProperty(ref isRepairOP10, value);
        }
        public bool IsRepairOP20
        {
            get => isRepairOP20; set => SetProperty(ref isRepairOP20, value);
        }

        public bool IsRepairOP30
        {
            get => isRepairOP30; set => SetProperty(ref isRepairOP30, value);
        }

        public bool IsRepairOP40
        {
            get => isRepairOP40; set => SetProperty(ref isRepairOP40, value);
        }
        public bool IsPrepareRepair
        {
            get => isPrepareRepair; set => SetProperty(ref isPrepareRepair, value);
        }
        public int StepIndex
        {
            get => stepIndex; set => SetProperty(ref stepIndex, value);
        }

        private int scanCode = -1;
        public MainWindowViewModel()
        {
            InitSerialPort();
            Service.StatusChangedEvent += Refresh;
        }

        private void Refresh(CommunicationModel model)
        {
            try
            {
                OnTipChanged(model);
                OnAlarmTipChanged(model);
                OnWarningChanged(model);
                scanCode = model.ScanCode;
                //TightenGun1
                Tighten.IsPrepared = model.State[0];
                Tighten.IsRunning = model.State[1];
                Tighten.IsBreakdown = model.State[2];
                Tighten.IsOK = model.State[3];
                Tighten.IsNG = model.State[4];
                Tighten.CurProgramNum = model.Shorts[1];
                Tighten.Torsion = model.Floats[0];
                Tighten.Angle = model.Floats[1];
                Tighten.CurX = model.Floats[2];
                Tighten.CurY = model.Floats[3];
                Tighten.SetX = model.Floats[4];
                Tighten.SetY = model.Floats[5];
                Tighten.Count = model.Floats[6];
                for (int i = 0; i < model.StepTips.Count; i++)
                {
                    if (model.StepTips[i])
                    {
                        StepIndex = i % 10;
                        break;
                    }
                    StepIndex = -1;
                }

                resetShiftBtnTrigger.Clk = model.ShiftButtons[5];
                sendMsgTrigger.Clk = model.CollectFlag == 1;
                if (sendMsgTrigger.Q)
                {
                    byte[] feedback = Int.ToByteArray(2);
                    //回复PLC采集成功
                    Service.WriteMesData(580, feedback);
                    //var year = System.DateTime.Now.Year.ToString().Substring(2);
                    //var mon = System.DateTime.Now.Month.ToString("D2");
                    //var day = System.DateTime.Now.Day.ToString("D2");
                    //var hour = System.DateTime.Now.Hour.ToString("D2");
                    //var min = System.DateTime.Now.Minute.ToString("D2");
                    //var sec = System.DateTime.Now.Second.ToString("D2");
                    identity.TrayId = TrayID;
                    identity.OP10PartCode1 = OP10Code1;
                    identity.OP10PartCode2 = OP10Code2;
                    identity.OP20PartCode = OP20Code;
                    identity.OP30PartCode = OP30Code;
                    identity.IsRepair = true;
                    identity.OP10Result = model.Devs[0].Result == 1 ? "OK" : "NG";
                    identity.OP20Result = model.Devs[1].Result == 1 ? "OK" : "NG";
                    identity.OP30Result = model.Devs[3].Result == 1 ? "OK" : "NG";
                    identity.OP20Angle1 = (int)model.Devs[0].Datas[1];
                    identity.OP20Angle2 = (int)model.Devs[1].Datas[1];
                    identity.OP20Torque1 = (int)model.Devs[0].Datas[0];
                    identity.OP20Torque2 = (int)model.Devs[1].Datas[0];

                    identity.OP30Angle1 = (int)model.Devs[2].Datas[1];
                    identity.OP30Angle2 = (int)model.Devs[3].Datas[1];
                    identity.OP30Angle3 = (int)model.Devs[4].Datas[1];
                    identity.OP30Angle4 = (int)model.Devs[5].Datas[1];
                    identity.OP30Torque1 = (int)model.Devs[2].Datas[0];
                    identity.OP30Torque2 = (int)model.Devs[3].Datas[0];
                    identity.OP30Torque3 = (int)model.Devs[4].Datas[0];
                    identity.OP30Torque4 = (int)model.Devs[5].Datas[0];
                    SaveRepairInfo(identity);
                    //OP10Code1 = OP10Code2 = OP20Code = OP30Code = string.Empty;
                }
                if (resetShiftBtnTrigger.Q)
                {
                    bool[] datas = new bool[4] { false, false, false, false };
                    Service.WriteData(0, datas);
                    IsEnableOP10 = IsEnableOP20 = IsEnableOP30 = IsEnableOP40 = true;
                }
            }
            catch (Exception ex)
            {
                //DbHelper.LogTip(ex.ToString());
            }
        }

        public void OnRepair(int index)
        {
            IsRepairOP10 = IsRepairOP20 = IsRepairOP30 = IsRepairOP40 = false;
            IsEnableOP10 = IsEnableOP20 = IsEnableOP30 = IsEnableOP40 = false;
            switch (index)
            {
                case 0: IsRepairOP10 = true; IsEnableOP10 = true; break;
                case 1: IsRepairOP20 = true; IsEnableOP20 = true; break;
                case 2: IsRepairOP30 = true; IsEnableOP30 = true; break;
                case 3: IsRepairOP40 = true; IsEnableOP40 = true; break;
                default: break;
            }
        }
        private void InitSerialPort()
        {
            serialPort.PortName = Service.config.ScanComPort;
            serialPort.BaudRate = Service.config.ScanBaudrate;
            serialPort.DataBits = 8;
            serialPort.Parity = Parity.None;
            serialPort.StopBits = StopBits.One;
            serialPort.DataReceived += SerialPortRecv;
            try
            {
                serialPort.Open();
                //DbHelper.LogTip($"串口已连接: Port : {serialPort.PortName}  Baudrate: {serialPort.BaudRate}");
            }
            catch (Exception ex)
            {
                MessageBox.Show("串口连接失败:" + ex.Message);
            }
        }

        private int count = 0;
        private void SerialPortRecv(object sender, SerialDataReceivedEventArgs e)
        {
            if (scanCode != 1)
            {
                //DbHelper.LogTip("未检测到允许扫码条件");
                return;
            }
            Thread.Sleep(200);
            int len = serialPort.BytesToRead;
            byte[] datas = new byte[len];
            serialPort.Read(datas, 0, len);
            string temp = Encoding.ASCII.GetString(datas);
            //DbHelper.LogTip($"{temp}");

            if (isRepairOP10)
            {
                OP10Code = temp.Trim();
                count++;
                if (count == 1)
                {
                    OP10Code1 = temp.Trim();
                }
                else if (count == 2)
                {
                    OP10Code2 = temp.Trim();
                }
            }
            else
            {
                count = 0;
            }
            if (isRepairOP20) OP20Code = temp.Trim();
            if (isRepairOP30) OP30Code = temp.Trim();
            if (isRepairOP40) OP40Code = temp.Trim();
            Service.WriteData(70, Int.ToByteArray(2));
        }

        public void OnTipChanged(CommunicationModel communication)
        {
            for (int i = 0; i < communication.Prompt.Length; i++)
            {
                Msg model = new Msg();
                model.DateTime = System.DateTime.Now;
                model.MsgType = "Tip";
                model.Index = i + 1;
                if (MsgHelper.TipInfoDic.ContainsKey(model.Index))
                {
                    model.msg = MsgHelper.TipInfoDic[model.Index];
                }
                var alarm = Messages.Where(o => o.Index == model.Index && o.MsgType == "Tip").FirstOrDefault();
                //判断消除和添加
                if (communication.Prompt[i])
                {
                    if (alarm == null)
                    {
                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            Messages.Insert(0, model);
                        });
                    }
                }
                else
                {
                    if (alarm != null)
                    {
                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            Messages.Remove(alarm);
                        });
                    }
                }
            }
        }

        public void OnAlarmTipChanged(CommunicationModel communication)
        {
            for (int i = 0; i < communication.Alarm.Length; i++)
            {
                Msg model = new Msg();
                model.DateTime = System.DateTime.Now;
                model.MsgType = "Alarm";
                model.Index = i + 1;
                if (MsgHelper.AlarmDic.ContainsKey(model.Index))
                {
                    model.msg = MsgHelper.AlarmDic[model.Index];
                }
                var alarm = Messages.Where(o => o.Index == model.Index && o.MsgType == "Alarm").FirstOrDefault();
                //判断消除和添加
                if (communication.Alarm[i])
                {
                    if (alarm == null)
                    {
                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            Messages.Insert(0, model);
                        });
                    }
                }
                else
                {
                    if (alarm != null)
                    {
                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            Messages.Remove(alarm);
                        });

                    }
                }
            }
        }

        public void OnWarningChanged(CommunicationModel communication)
        {
            for (int i = 0; i < communication.Warning.Length; i++)
            {
                Msg model = new Msg();
                model.DateTime = System.DateTime.Now;
                model.MsgType = "Warning";
                model.Index = i + 1;
                if (MsgHelper.WarningDic.ContainsKey(model.Index))
                {
                    model.msg = MsgHelper.WarningDic[model.Index];
                }
                var alarm = Messages.Where(o => o.Index == model.Index && o.MsgType == "Warning").FirstOrDefault();
                //判断消除和添加
                if (communication.Warning[i])
                {
                    if (alarm == null)
                    {
                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            Messages.Insert(0, model);
                        });
                    }
                }
                else
                {
                    if (alarm != null)
                    {
                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            Messages.Remove(alarm);
                        });

                    }
                }
            }
        }

        public void LoadStepTip(string name, bool result)
        {
            if (result) return;
            StepTips.Clear();
            var info = MsgHelper.StepTipDic.Where(o => o.Name == name).FirstOrDefault();
            if (info != null && info.Infos.Count > 0)
            {
                foreach (var msg in info.Infos)
                {
                    Msg model = new Msg();
                    model.Index = msg.Key;
                    model.msg = msg.Desc;
                    StepTips.Add(model);
                }
            }
        }

        object _locker = new object();
        #region Sqlite
        public void SaveRepairInfo(ProductIdentity identity)
        {
            Task.Run(() =>
            {
                lock (_locker)
                {
                    try
                    {
                        using (ProductionQueryContext db = new ProductionQueryContext())
                        {
                            db.Product.Add(identity);
                            db.SaveChanges();
                        }
                    }
                    catch { }
                }
            });
        }
        #endregion
    }
}
